// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证（版本 2.0）进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动！任何基于本项目二次开发而产生的一切法律纠纷和责任，我们不承担任何责任！

using Admin.NET.Core.Service.Warehouse.Dto;
using System.ComponentModel;
using Mapster;
using Admin.NET.Application;
using Admin.NET.Application.Entity;

namespace Admin.NET.Core.Service.Warehouse;

/// <summary>
/// 仓库管理服务 🧩
/// </summary>
[ApiDescriptionSettings(Order = 200, Description = "仓库管理")]
public class WarehouseService : IDynamicApiController, ITransient
{
    private readonly SqlSugarRepository<WarehouseModel> _warehouseRep;
    private readonly SqlSugarRepository<SysOrg> _sysOrgRep;
    private readonly SqlSugarRepository<SysUser> _sysUserRep;
    private readonly SqlSugarRepository<WarePlaceModel> _warePlaceRep;
    

    public WarehouseService(
        SqlSugarRepository<WarehouseModel> warehouseRep,
        SqlSugarRepository<SysOrg> sysOrgRep,
        SqlSugarRepository<SysUser> sysUserRep,
        SqlSugarRepository<WarePlaceModel> wareplaceRep)
    {
        _warehouseRep = warehouseRep;
        _sysOrgRep = sysOrgRep;
        _sysUserRep = sysUserRep;
        _warePlaceRep = wareplaceRep;
    }

    /// <summary>
    /// 获取仓库分页列表 🔖
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [HttpGet]
    [DisplayName("获取仓库分页列表")]
    public async Task<SqlSugarPagedList<WarehouseListOutput>> Page(WarehousePageInput input)
    {
        var warehouses = await _warehouseRep.AsQueryable()
            .LeftJoin<SysOrg>((w, o) => w.DepartmentId == o.Id)
            .LeftJoin<SysUser>((w, o, u) => w.UserId == u.Id)
            .WhereIF(!string.IsNullOrWhiteSpace(input.Keyword), (w, o, u) => 
                w.WareName.Contains(input.Keyword.Trim()) || 
                w.WareCode.Contains(input.Keyword.Trim()))
            .WhereIF(input.WareType.HasValue, (w, o, u) => w.WareType == input.WareType.Value)
            .WhereIF(input.DepartmentId.HasValue, (w, o, u) => w.DepartmentId == input.DepartmentId.Value)
            .WhereIF(input.UserId.HasValue, (w, o, u) => w.UserId == input.UserId.Value)
            .OrderBy((w, o, u) => w.CreateTime, OrderByType.Desc)
            .Select((w, o, u) => new WarehouseListOutput
            {
                Id = w.Id,
                WareCode = w.WareCode,
                WareName = w.WareName,
                WareVolume = w.WareVolume,
                DepartmentName = o.Name,
                UserName = u.RealName,
                WareAddr = w.WareAddr,
                WareType = w.WareType,
                WareLock = w.WareLock,
                WarePlaceId = w.WarePlaceId,
                WareNote = w.WareNote,
                CreateTime = w.CreateTime
            })
            .ToPagedListAsync(input.Page, input.PageSize);

        return warehouses;
    }

    /// <summary>
    /// 获取仓库列表 🔖
    /// </summary>
    /// <returns></returns>
    [DisplayName("获取仓库列表")]
    [HttpGet]
    public async Task<List<WarehouseListOutput>> List()
    {
        var warehouses = await _warehouseRep.AsQueryable()
            .LeftJoin<SysOrg>((w, o) => w.DepartmentId == o.Id)
            .LeftJoin<SysUser>((w, o, u) => w.UserId == u.Id)
            .Where((w, o, u) => w.WareType == true) // 只显示启用的仓库
            .OrderBy((w, o, u) => w.CreateTime, OrderByType.Desc)
            .Select((w, o, u) => new WarehouseListOutput
            {
                Id = w.Id,
                WareCode = w.WareCode,
                WareName = w.WareName,
                WareVolume = w.WareVolume,
                DepartmentName = o.Name,
                UserName = u.RealName,
                WareAddr = w.WareAddr,
                WareType = w.WareType,
                WareLock = w.WareLock,
                WarePlaceId = w.WarePlaceId,
                WareNote = w.WareNote,
                CreateTime = w.CreateTime
            })
            .ToListAsync();

        return warehouses;
    }

    /// <summary>
    /// 获取仓库详情 🔖
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    [DisplayName("获取仓库详情")]
    [HttpGet]
    public async Task<WarehouseOutput> Detail(long id)
    {
        var warehouse = await _warehouseRep.AsQueryable()
            .LeftJoin<SysOrg>((w, o) => w.DepartmentId == o.Id)
            .LeftJoin<SysUser>((w, o, u) => w.UserId == u.Id)
            .Where((w, o, u) => w.Id == id)
            .Select((w, o, u) => new WarehouseOutput
            {
                Id = w.Id,
                WareCode = w.WareCode,
                WareName = w.WareName,
                WareVolume = w.WareVolume,
                DepartmentId = w.DepartmentId,
                DepartmentName = o.Name,
                UserId = w.UserId,
                UserName = u.RealName,
                WareAddr = w.WareAddr,
                WareType = w.WareType,
                WareLock = w.WareLock,
                WarePlaceId = w.WarePlaceId,
                WareNote = w.WareNote,
                CreateTime = w.CreateTime,
                UpdateTime = w.UpdateTime,
                CreateUserId = w.CreateUserId,
                CreateUserName = w.CreateUserName,
                UpdateUserId = w.UpdateUserId,
                UpdateUserName = w.UpdateUserName
            })
            .FirstAsync();

        return warehouse ?? throw Oops.Oh("仓库不存在");
    }

    /// <summary>
    /// 添加仓库 🔖
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [HttpPost]
    [DisplayName("添加仓库")]
    [ApiDescriptionSettings(Name = "Add"), HttpPost]
    public async Task<long> Add(AddWarehouseInput input)
    {
        // 检查仓库名称是否重复
        var isExist = await _warehouseRep.IsAnyAsync(w => w.WareName == input.WareName);
        if (isExist)
            throw Oops.Oh("仓库名称已存在");

        var entity = input.Adapt<WarehouseModel>();
        entity.WareCode = await GenerateWareCode(); // 自动生成仓库编码

        await _warehouseRep.InsertAsync(entity);
        return entity.Id;
    }

    /// <summary>
    /// 更新仓库 🔖
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [ApiDescriptionSettings(Name = "Update"), HttpPost]
    [DisplayName("更新仓库")]
    public async Task Update(UpdateWarehouseInput input)
    {
        var entity = await _warehouseRep.GetByIdAsync(input.Id);
        if (entity == null)
            throw Oops.Oh("仓库不存在");

        // 检查仓库名称是否重复（排除自己）
        var isExist = await _warehouseRep.IsAnyAsync(w => w.WareName == input.WareName && w.Id != input.Id);
        if (isExist)
            throw Oops.Oh("仓库名称已存在");

        input.Adapt(entity);
        await _warehouseRep.UpdateAsync(entity);
    }

    /// <summary>
    /// 删除仓库 🔖
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [ApiDescriptionSettings(Name = "Delete"), HttpPost]
    [DisplayName("删除仓库")]
    public async Task Delete(DeleteWarehouseInput input)
    {
        var entity = await _warehouseRep.GetByIdAsync(input.Id);
        if (entity == null)
            throw Oops.Oh("仓库不存在");

        await _warehouseRep.DeleteByIdAsync(input.Id);
    }

    /// <summary>
    /// 获取部门列表（用于下拉框）🔖
    /// </summary>
    /// <returns></returns>
    [DisplayName("获取部门列表")]
    public async Task<List<SelectOption>> GetDepartmentList()
    {
        var departments = await _sysOrgRep.AsQueryable()
            .Where(o => o.Status == StatusEnum.Enable)
            .OrderBy(o => o.OrderNo)
            .Select(o => new SelectOption
            {
                Value = o.Id.ToString(),
                Label = o.Name
            })
            .ToListAsync();

        return departments;
    }

    /// <summary>
    /// 获取用户列表（用于下拉框）🔖
    /// </summary>
    /// <returns></returns>
    [DisplayName("获取用户列表")]
    public async Task<List<SelectOption>> GetUserList()
    {
        var users = await _sysUserRep.AsQueryable()
            .Where(u => u.Status == StatusEnum.Enable)
            .OrderBy(u => u.RealName)
            .Select(u => new SelectOption
            {
                Value = u.Id.ToString(),
                Label = u.RealName
            })
            .ToListAsync();

        return users;
    }

    /// <summary>
    /// 生成仓库编码
    /// </summary>
    /// <returns></returns>
    private async Task<string> GenerateWareCode()
    {
        var maxCode = await _warehouseRep.AsQueryable()
            .Where(w => w.WareCode.StartsWith("WH"))
            .OrderBy(w => w.WareCode, OrderByType.Desc)
            .Select(w => w.WareCode)
            .FirstAsync();

        if (string.IsNullOrEmpty(maxCode))
        {
            return "WH001";
        }

        var number = int.Parse(maxCode.Substring(2)) + 1;
        return $"WH{number:D3}";
    }

    #region 库位管理接口

    /// <summary>
    /// 获取库位分页列表 🔖
    /// </summary>
    /// <param name = "input" ></ param >
    /// < returns ></ returns >
    [HttpGet]
    [DisplayName("获取库位分页列表")]
    public async Task<SqlSugarPagedList<WarePlaceModelOutput>> GetWarePlacePage(PageWarePlaceModelInput input)
    {
        input.Keyword = input.Keyword?.Trim();
        var query = _warePlaceRep.AsQueryable()
            .WhereIF(!string.IsNullOrWhiteSpace(input.Keyword), u => u.WarePlaceCode.Contains(input.Keyword) || u.WarePlaceName.Contains(input.Keyword) || u.WarePlaceNote.Contains(input.Keyword))
            .WhereIF(!string.IsNullOrWhiteSpace(input.WarePlaceCode), u => u.WarePlaceCode.Contains(input.WarePlaceCode.Trim()))
            .WhereIF(!string.IsNullOrWhiteSpace(input.WarePlaceName), u => u.WarePlaceName.Contains(input.WarePlaceName.Trim()))
            .WhereIF(!string.IsNullOrWhiteSpace(input.WarePlaceNote), u => u.WarePlaceNote.Contains(input.WarePlaceNote.Trim()))
            .WhereIF(input.WarePlaceVolume != null, u => u.WarePlaceVolume == input.WarePlaceVolume)
            .WhereIF(input.UserId != null, u => u.UserId == input.UserId)
            .WhereIF(input.WarePlaceType.HasValue, u => u.WarePlaceType == input.WarePlaceType)
            .Select<WarePlaceModelOutput>();
        return await query.OrderBuilder(input).ToPagedListAsync(input.Page, input.PageSize);
    }

    /// <summary>
    /// 获取库位列表 🔖
    /// </summary>
    /// <returns></returns>
    [DisplayName("获取库位列表")]
    [HttpGet]
    public async Task<List<WarePlaceModelOutput>> GetWarePlaceList()
    {
        var warePlaces = await _warePlaceRep.AsQueryable()
            .Where(w => w.IsDelete == false) // 只显示未删除的库位
            .OrderBy(w => w.CreateTime, OrderByType.Desc)
            .Select<WarePlaceModelOutput>()
            .ToListAsync();

        return warePlaces;
    }

    #endregion
}

/// <summary>
/// 下拉框选项
/// </summary>
public class SelectOption
{
    /// <summary>
    /// 值
    /// </summary>
    public string Value { get; set; }

    /// <summary>
    /// 标签
    /// </summary>
    public string Label { get; set; }
}
